Stripe API Design Evaluation and Latency Budget

Learn how Stripe API meets different non-functional requirements.

As we have seen, Stripe plays an important role in the payment ecosystem and makes the payment process smooth via the API endpoints we provided in the previous lesson. While we achieved different functional requirements through these endpoints, we still have to focus on the non-functional requirements we identified in the initial lesson. This lesson will describe how we achieve the non-functional requirements and different optimization strategies to improve the efficiency and response time of our service. Toward the end, we will also compute the response time of the Stripe API.

Non-functional requirements#

The following section discusses how Stripe API meets the non-functional requirements.

Strong consistency#

Due to the nature of the API that involves operations on critical data and financial data, strong consistency is paramount for the Stripe API. The Stripe API is strongly consistent and provides consistent data at every level by adopting the following measures:

  • Exactly once semantics: Idempotency keys are used in the API call where the non-idempotent method needs to be used, such as the POST HTTP method. This way, we avoid multiple operations where only one operation needs to be performed.

  • Reconciliation: The internal system's services periodically communicate with each other to compare their statuses to confirm that they are in agreement. According to some studies, this is the last line of defense in the payment system. Reconciliation not only improves the security of the payment system but also makes the system internally consistent.

Point to Ponder

Question

Why is reconciliation in the payment system considered the last line of defense?

Hide Answer

The reconciliation ensures that the payment owed and due match the transactions that have been completed. In case of transaction ambiguities, it is considered that either the system security is compromised or any other fraudulent activity has occurred. An example where reconciliation would help is given below:

Assume a customer buys some goods and pays via their credit card. Ultimately, the bill provided to the customer has a different amount and date from what is present in Stripe records. Such discrepancies can be detected via the reconciliation process by comparing the records in Stripe and the bill provided to the customer.

Security#

To ensure secure communication and data transfer, we use a number of techniques. Firstly, we use the HSTS (HTTP strict transport security) mechanism to avoid man-in-the-middle attacks and ensure that the applications or browsers use HTTP protocol over TLS to comply with PCI standards. Secondly, the credit or debit card numbers are encrypted with advanced encryption algorithms such as AES-256 during storage (or in transit). Similarly, a session is created with Stripe to process the payment securely when a user aims to pay for a product.

Note: Stripe uses a number of machine learning systems known as radars that use hundreds of signals and heuristics to detect and prevent fraud.

Reliability#

Data is replicated along multiple databases to increase reliability and durability. For this purpose, we use a mix of SQL and NoSQL databases for storing various types of data. We need an SQL database for storing customers' and accounts' data, while for unstructured data such as invoices, transactions, and charges, we use a NoSQL database. NoSQL database not only provides reliability but also aids in high availability and increased performance for unstructured data, which makes it an ideal choice for Stripe. Similarly, we replicate data across multiple regions and take regular snapshots to prevent data loss.

Availability#

To increase the system's availability, we adopt proper rate limiting, monitoring, and automated recovery mechanisms. Apart from increasing the system's availability, we also ensure strong consistency because of its significance in the payment ecosystem. However, there may often be a trade-off between availability and performance, on the one hand, and consistency, on the other, depending on the nature of the current use case.

Scalability#

The scalability of API can be increased by adding more capacity to the infrastructure to handle a large number of businesses and customer requests. Although the Stripe service also depends on other services (for example, cards networks) to scale effectively, here we only focus on the scalability of Stripe and assume that the other supporting services are scalable. Scaling other supporting services has monetary benefits for the providers. These monetary benefits are incentives for high scalability and high availability.

Achieving Non-Functional Requirements

Non-Functional Requirements

Approaches

Strong consistency

  • Exactly once semantic
  • Reconciliation


Security

  • Using HSTS protocol
  • Using 256-bit AES symmetric encryption
  • Session to process a payment

Reliability

  • Data replication in multiple databases
  • A mix of relational and non-relational databases

Availability

  • Rate limiting, monitoring, and automated recovery mechanisms

Scalability

  • Adding more capacity to the infrastructure

Latency budget#

Let's calculate the message size before moving toward latency and processing time.

As discussed in the back-of-the-envelope latency calculations, the latency of the GET and POST requests are affected by two different parameters. In the case of GET, the average RTTRTT remains the same regardless of the data size (due to the small request size), and the time to download the response varies by 0.4 ms0.4\ ms per KB. Similarly, for POST requests, the RTTRTT time changes with the data size by 1.15 ms1.15\ ms per KB from the base RTT time, which was 260 ms.

Message size#

As in the previous lesson, we discussed some selective endpoints of different services due to their repetitive nature. This applies to estimating the sizes of GET or POST methods as well. All the GET or POST requests carry approximately equal sizes. Therefore, we only consider the request to retrieve or create an invoice to estimate the size. The GET request to retrieve the invoice only contains the invoice ID; therefore, its size is considered up to 1 KB. However, the responses of any request contain all the parameters relevant to an invoice; therefore, we assume their sizes will not exceed 5 KB. Each request and response size is given below:

  • GET request size to retrieve an invoice: In the GET request, we only pass the invoice ID in as a query parameter; therefore, we consider the whole request size to be around 1 KB1\ KB.

  • GET response size to retrieve an invoice: The response to retrieve an invoice contains several parameters (no more than 30); therefore, its size will not be more than 5 KB5\ KB.

  • POST request size to create an invoice: The request contains approximately the same parameters as in the GET response; consequently, we consider its size to be 5 KB5\ KB.

  • POST response size to create an invoice: Since we would receive the same parameters in the response as the one we pass in the request, the response size will also remain up to 5 KB5\ KB.

Response time#

The following calculator computes the minimum and maximum response time of the GET method:

Response Time Calculator to Retrieve an Invoice

Enter the size in KBs5KB
Minimum latencyf192.5ms
Maximum latencyf273.5ms
Minimum response timef196.5ms
Maximum response timef277.5ms

Assuming the response size is 5 KB, then the latency is calculated by:

Timelatency_min=Timebase_min+RTTget+0.4×size of response (KBs)=120.5+70+0.4×5=192.5 msTime_{latency\_min} = Time_{base\_min} + RTT_{get} + 0.4 \times size\ of\ response\ (KBs) = 120.5 + 70 + 0.4 \times 5 = 192.5\ ms

Timelatency_max=Timebase_max+RTTget+0.4×size of response (KBs)=201.5+70+0.4×5=273.5 msTime_{latency\_max} = Time_{base\_max} + RTT_{get} + 0.4 \times size\ of\ response\ (KBs) = 201.5 + 70 + 0.4 \times 5 = 273.5\ ms

Similarly, the response time is calculated using the following equation:

TimeResponse=Timelatency+TimeprocessingTime_{Response} = Time_{latency}+ Time_{processing}

Now, for minimum response time, we use minimum values of base time and processing time:

TimeResponse_min=Timelatency_min+Timeprocessing_min=192.5 ms+4 ms=196.5 msTime_{Response\_min} = Time_{latency\_min}+ Time_{processing\_min}= 192.5\ ms + 4\ ms = 196.5\ ms

Now, for maximum response time, we use maximum values of base time and processing time:

TimeResponse_max=Timelatency_max+Timeprocessing_max=273.5 ms+4 ms=277.5 msTime_{Response\_max} = Time_{latency\_max}+ Time_{processing\_max}= 273.5\ ms + 4\ ms = 277.5\ ms

For the POST request to create an invoice, we consider the minimum and maximum response times for both the request and response of the POST method in the following calculator:

Response Time Calculator to Create an Invoice

Enter the size in KBs5KB
Minimum latencyf386.65ms
Maximum latencyf467.65ms
Minimum response timef390.65ms
Maximum response timef471.65ms

Assuming the request size is 5 KB:

Timelatency=Timebase+RTTpost+DownloadTime_{latency} = Time_{base} + RTT_{post} + Download

RTTpost=RTTbase+1.15×Size=260 ms+1.15 ms×5 KBsRTT_{post} = RTT_{base}+1.15\times Size = 260\ ms + 1.15\ ms\times 5\ KBs

Timelatency_min=Timebase_min+(RTTbase+1.15×size of request (KBs))+0.4Time_{latency\_min} = Time_{base\_min} + (RTT_{base} + 1.15 \times size\ of\ request\ (KBs)) + 0.4

=120.5+(260+1.15×5)+0.4=386.65 ms= 120.5 + (260 + 1.15 \times 5) + 0.4 = 386.65\ ms

Timelatency_max=Timebase_max+(RTTbase+1.15×size of request (KBs))+0.4Time_{latency\_max} = Time_{base\_max} + (RTT_{base} + 1.15\times size\ of\ request\ (KBs)) + 0.4

=201.5+260+1.15×5+0.4=467.65 ms= 201.5 + 260 + 1.15 \times 5 + 0.4 = 467.65\ ms

Similarly, the response time is calculated as:

TimeResponse_min=Timelatency_min+Timeprocessing_min=386.65 ms+4 ms=390.65 msTime_{Response\_min} = Time_{latency\_min}+ Time_{processing\_min}= 386.65\ ms + 4\ ms = 390.65\ ms

TimeResponse_max=Timelatency_max+Timeprocessing_max=467.65 ms+4 ms=471.65 msTime_{Response\_max} = Time_{latency\_max}+ Time_{processing\_max}= 467.65\ ms + 4\ ms = 471.65\ ms

The Stripe API processing time in terms of GET and POST requests
The Stripe API processing time in terms of GET and POST requests

We have calculated the maximum response times for the GET and POST requests, which are, 277.5 ms277.5\ ms and 471.65 ms471.65\ ms, respectively. Since the response time for an effective API is considered to be 1 second; therefore, according to our estimations, our proposed Stripe API has a satisfactory response time within the expected range.

Note: The API response size we calculated earlier is purely based on the interaction with Stripe services. We have seen that Stripe acts as a payment gateway in the payment ecosystem. Therefore, information and payment processing flow through many entities involved in the ecosystem, which affects the processing time of our API. For example, verification of customer information, such as credit or debit card information and the validity of their account in the issuing bank, may have an impact on the processing time. In light of this, the successful payment may take time, ranging from several seconds to several days.

In this chapter, we designed an API for Stripe (payment gateway). The Stripe API has a complex nature that involves various operations and services to be implemented carefully to meet the needs of a wide range of users and businesses across the globe. Similarly, identifying endpoints and micro-services requires rigorous attention to meet different functional requirements, and the communication between different organizations (entities) needs to be PCI compliant. Designing Stripe API also involves careful consideration and implementation of various non-functional requirements, such as consistency, security, reliability, availability, and scalability.

Stripe Interaction with Cards Network

Requirements of the Twitter API